.\"
.\" This file and its contents are supplied under the terms of the
.\" Common Development and Distribution License ("CDDL"), version 1.0.
.\" You may only use this file in accordance with the terms of version
.\" 1.0 of the CDDL.
.\"
.\" A full copy of the text of the CDDL should have accompanied this
.\" source.  A copy of the CDDL is also available via the Internet at
.\" http://www.illumos.org/license/CDDL.
.\"
.\"
.\" Copyright 2016 Joyent, Inc.
.\"
.Dd Dec 22, 2016
.Dt USBA_HCDI_PIPE_CTRL_XFER 9E
.Os
.Sh NAME
.Nm usba_hcdi_pipe_ctrl_xfer
.Nd perform a USB control transfer
.Sh SYNOPSIS
.In sys/usb/usba/hcdi.h
.Ft int
.Fo prefix_hcdi_pipe_ctrl_xfer
.Fa "usba_pipe_handle_data_t *ph"
.Fa "usb_ctrl_req_t *ucrp"
.Fa "usb_flags_t usb_flags"
.Fc
.Sh INTERFACE LEVEL
.Sy Volatile -
illumos USB HCD private function
.Pp
This is a private function that is not part of the stable DDI.
It may be removed or changed at any time.
.Sh PARAMETERS
.Bl -tag -width Fa
.It Fa ph
A pointer to a USB pipe handle as defined in
.Xr usba_pipe_handle_data 9S .
.It Fa ucrp
A pointer to a USB control transfer request.
The structure's members are documented in
.Xr usb_ctrl_req 9S .
.It Fa usb_flags
Flags which describe how allocations should be performed.
Valid flags are:
.Bl -tag -width Sy
.It Sy USB_FLAGS_NOSLEEP
Do not block waiting for memory.
If memory is not available the allocation will fail.
.It Sy USB_FLAGS_SLEEP
Perform a blocking allocation.
If memory is not available, the function will wait until memory is made
available.
.Pp
Note, the request may still fail even if
.Sy USB_FLAGS_SLEEP
is specified.
.El
.El
.Sh DESCRIPTION
The
.Fn usba_hcdi_pipe_ctrl_xfer
entry point is used to initiate an
.Em asynchronous
USB Control transfer on the pipe
.Fa ph .
The specific USB control transfer is provided in
.Fa ucrp .
For more background on transfer types, see
.Xr usba_hcdi 9E .
.Pp
The host controller driver should first check the USB address of the
pipe handle.
It may correspond to the root hub.
If it does, rather than initiating an I/O transfer, the driver may need to
emulate it using available information.
.Pp
Control endpoints are always bi-directional.
A given endpoint may perform transfer data from the OS to the device, or from
the device to the OS.
The driver will need to look at the control transfer request and transform that
into the appropriate format for the controller.
.Pp
Control transfers are made up of three parts.
A setup stage, an optional data stage, and a status stage.
Depending on the controller, the driver may need to transform the transfer
request into a format that matches this.
Refer to the device's controller specification for more information on whether
this is required or not.
.Pp
The device driver should a request based on the information present in
the control request
.Fa ucrp .
If there is a non-zero length for the transfer, indicated by the
.Sy ctrl_wLength
member of
.Fa ucrp
being greater than zero, then the controller needs to allocate a
separate memory buffer for the request.
The corresponding data will be found in an
.Xr mblk 9S
structure as the
.Sy ctrl_data
member of
.Fa ucrp .
.Pp
If this transfer needs to be sent to a device through the controller and
is not being handled directly by the driver, then the driver should
allocate a separate region of memory (generally memory suitable for a
DMA transfer) for the transfer.
If sending data to the device, the data in the message block should be copied
prior to the transfer.
Otherwise, once the transfer completes, data should be transferred into the
message block and the write pointer incremented.
.Pp
If the driver needs to allocate memory for this transfer, it should
honor the values set in
.Fa usb_flags
to indicate whether or not it should block for memory, whether DMA
memory or normal kernel memory.
.Pp
If the driver successfully schedules the I/O or it can handle the I/O
itself because it's a synthetic root hub request, then it should return
.Sy USB_SUCCESS .
If the driver returns successfully, it must call
.Xr usba_hcdi_cb 9F
with
.Fa ucrp
either before or after it returns.
The only times that a driver would call the callback before the function returns
are for requests to the root hub that it handles inline and does not need to
send off asynchronous activity to the controller.
.Pp
For asynchronous requests, the controller is also responsible for
timing out the request if it does not complete.
If the timeout in the request as indicated in the
.Sy ctrl_timeout
member is set to zero, then the driver should use the USBA default
timeout of
.Sy HCDI_DEFAULT_TIMEOUT .
All timeout values are in
.Em seconds .
.Ss Callback Handling
When the control transfer completes the driver should consider the
following items to determine what actions it should take on the callback:
.Bl -bullet
.It
If the transfer timed out, it should remove the transfer from the
outstanding list, queue the next transfer, and return the transfer back
to the OS with the error code
.Sy USB_CR_TIMEOUT
with
.Xr usba_hcdi_cb 9F .
.It
If the transfer failed, it should find the appropriate error and call
.Xr usba_hcdi_cb 9F
with that error.
.It
If the transfer succeeded, but less data was transferred than expected,
consult the
.Sy ctrl_attributes
member of the
.Fa ucrp .
If the
.Sy USB_ATTRS_SHORT_XFER_OK
flag is not present, then the driver should call
.Xr usba_hcdi_cb 9F
with the error
.Sy USB_CR_DATA_UNDERRUN .
.It
If the transfer was going to the host, then the driver should copy the
data into the transfer's message block and update the
.Sy b_wptr
member of the
.Xr mblk 9S .
.It
If everything was successful, call
.Xr usba_hcdi_cb 9F
with the code
.Sy USB_CR_OK .
.El
.Sh RETURN VALUES
Upon successful completion, the
.Fn usba_hcdi_pipe_ctrl_xfer
function should return
.Sy USB_SUCCESS .
Otherwise, it should return the appropriate USB error.
If uncertain, use
.Sy USB_FAILURE .
.Sh SEE ALSO
.Xr usba_hcdi 9E ,
.Xr usba_hcdi_cb 9F ,
.Xr mblk 9S ,
.Xr usb_ctrl_req 9S ,
.Xr usba_pipe_handle_data 9S
